﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml.Serialization;
using System.IO;
using Sirenix.OdinInspector;

namespace Data
{
    /// <summary>
    /// 动作组
    /// </summary>
    [Serializable]
    public class ActionGroup : ICloneable
    {
        #region boundbox
        [LabelText("单位的包围盒长度，包围盒用来检测受击范围等")]
        [VerticalGroup("Split")]
        [FoldoutGroup("Split/包围盒", false)]
        private int mBoundingLength = 80;

        [Category("包围盒")]
        [Description("单位的包围盒长度，包围盒用来检测受击范围等。")]
        [DisplayName("包围盒长度(z)")]
        [DefaultValue(80)]
        public int BoundingLength { get { return mBoundingLength; } set { mBoundingLength = value; } }

        [LabelText("单位的包围盒宽度")]
        [FoldoutGroup("Split/包围盒")]
        private int mBoundingWidth = 80;

        [Category("包围盒")]
        [Description("单位的包围盒宽度，包围盒用来检测受击范围等。")]
        [DisplayName("包围盒宽度(x)")]
        [DefaultValue(80)]
        public int BoundingWidth { get { return mBoundingWidth; } set { mBoundingWidth = value; } }

        [LabelText("单位的包围盒高度")]
        [FoldoutGroup("Split/包围盒")]
        private int mBoundingHeight = 180;

        [Category("包围盒")]
        [Description("单位的包围盒高度，包围盒用来检测受击范围等。")]
        [DisplayName("包围盒高度(y)")]
        [DefaultValue(180)]
        public int BoundingHeight { get { return mBoundingHeight; } set { mBoundingHeight = value; } }
        #endregion

        #region BoundOffset 
        [LabelText("单位的包围盒长度偏移值")]
        [VerticalGroup("Split")]
        [FoldoutGroup("Split/包围盒", false)]
        private int mBoundingLengthOffset = 0;

        [Category("包围盒")]
        [Description("单位的包围盒长度偏移值")]
        [DisplayName("包围盒长度(z)")]
        [DefaultValue(0)]
        public int BoundingLengthOffset { get { return mBoundingLengthOffset; } set { mBoundingLengthOffset = value; } }

        [LabelText("单位的包围盒宽度")]
        [FoldoutGroup("Split/包围盒")]
        private int mBoundingWidthOffset = 0;

        [Category("包围盒")]
        [Description("单位的包围盒宽度偏移值")]
        [DisplayName("包围盒宽度")]
        [DefaultValue(0)]
        public int BoundingWidthOffset { get { return mBoundingWidthOffset; } set { mBoundingWidthOffset = value; } }

        [LabelText("单位的包围盒高度")]
        [FoldoutGroup("Split/包围盒")]
        private int mBoundingHeightOffset = 0;

        [Category("包围盒")]
        [Description("单位的包围盒高度偏移值")]
        [DisplayName("包围盒高度")]
        [DefaultValue(0)]
        public int BoundingHeightOffset { get { return mBoundingHeightOffset; } set { mBoundingHeightOffset = value; } }
        #endregion

        #region hit result config
        [LabelText("能否被抓取")]
        [FoldoutGroup("Split/通用设置", false)]
        private bool mCanCapture = true;
        [DefaultValue(true), DisplayName("能否被抓取"), XmlAttribute("CanCapture")]
        [Category("受击结果")]
        public bool CanCapture { get { return mCanCapture; } set { mCanCapture = value; } }

        #endregion

        #region dead
        [LabelText("站立死亡动作")]
        [FoldoutGroup("Split/死亡", false)]
        private String mStandDeath = "H1040";
        [Description("站立死亡")]
        [DisplayName("站立死亡")]
        [Category("死亡")]
        [DefaultValue("H1040")]
        public String StandDeath { get { return mStandDeath; } set { mStandDeath = value; } }

        [LabelText("倒地死亡动作")]
        [FoldoutGroup("Split/死亡", false)]
        private String mDownDeath = "H1041";
        [Description("倒地死亡")]
        [DisplayName("倒地死亡")]
        [Category("死亡")]
        [DefaultValue("H1041")]
        public String DownDeath { get { return mDownDeath; } set { mDownDeath = value; } }

        #endregion

        #region other

        private List<Action> mActionList = new List<Action>();
        public List<Action> ActionList { get { return mActionList; } }

        //[FoldoutGroup("Split/AI设置", false)]
        //AISetting mAISetting = new AISetting();
        //[DisplayName("AI设置")]
        //public AISetting AISetting { get { return mAISetting; } set { mAISetting = value; } }

        
        [FoldoutGroup("Split/通用设置", false),LabelText("冲击减免,当怪物受到攻击时，冲击速度减免量，默认为不减免(1 1 1)")]
        private Vector3 mLashModifier = new Vector3(1, 1, 1);
        [Description("当怪物受到攻击时，冲击速度减免量，默认为不减免(1 1 1)")]
        [DisplayName("冲击减免")]
        public Vector3 LashModifier { get { return mLashModifier; } set { mLashModifier = value; } }


        [FoldoutGroup("Split/通用设置"),LabelText("动作组编号")]
        private int mGroupNum = 0;
        [DefaultValue(0)]
        [DisplayName("动作组编号")]
        public int GroupNum { get { return mGroupNum; } set { mGroupNum = value; } }

        [FoldoutGroup("Split/通用设置"), LabelText("角色的ID号")]
        private int mRace = 0;
        [Description("角色的ID号")]
        [DisplayName("角色ID")]
        public int Race { get { return mRace; } set { mRace = value; } }

        [FoldoutGroup("Split/通用设置"), LabelText("默认动作等级,单位的默认动作等级，用来进行霸体判断，每个动作可以重载动作等级。默认值为10")]
        private int mDefaultActionLevel = 10;
        [Description("单位的默认动作等级，用来进行霸体判断，每个动作可以重载动作等级。默认值为10")]
        [DisplayName("默认动作等级")]
        [DefaultValue(10)]
        public int DefaultActionLevel { get { return mDefaultActionLevel; } set { mDefaultActionLevel = value; } }

        [FoldoutGroup("Split/通用设置"),LabelText("起始动作(城镇)")]
        private String mStartupAction = "N0000";
        [Description("该单位(在城镇里面)创建出来时候的默认动作，默认值为N0000")]
        [DisplayName("起始动作(城镇)")]
        [DefaultValue("N0000")]
        public String StartupAction { get { return mStartupAction; } set { mStartupAction = value; } }

        [FoldoutGroup("Split/通用设置"), LabelText("起始动作(副本)")]
        private String mStartupActionInstance = "N0000";
        [Description("该单位(在副本里面)创建出来时候的默认动作，默认值为N0000")]
        [DisplayName("起始动作(副本)")]
        [DefaultValue("N0000")]
        public String StartupActionInstance { get { return mStartupActionInstance; } set { mStartupActionInstance = value; } }

        [FoldoutGroup("Split/通用设置")]
        private bool mHasCollision = false;
        [DefaultValue(false), DisplayName("是否生成碰撞"), XmlAttribute("HasCollision")]
        public bool HasCollision { get { return mHasCollision; } set { mHasCollision = value; } }

        [FoldoutGroup("Split/通用设置")]
        private bool mRotateOnHit = true;
        [DefaultValue(true), DisplayName("受击后转向"), XmlAttribute("RotateOnHit")]
        public bool RotateOnHit { get { return mRotateOnHit; } set { mRotateOnHit = value; } }

        [PropertyOrder(1)]
        [MultiLineProperty(3)]
        [FoldoutGroup("Split/通用设置")]
        private String mDesc = "";
        [DisplayName("说明")]
        [DefaultValue("")]
        public String Desc { get { return mDesc; } set { mDesc = value; } }

        [FoldoutGroup("Split/通用设置")]
        private bool mCheckDeath = false;
        [DefaultValue(false), DisplayName("侦测死亡"), XmlAttribute("CheckDeath")]
        public bool CheckDeath { get { return mCheckDeath; } set { mCheckDeath = value; } }
        #endregion

        #region gravity
        [FoldoutGroup("Split/通用设置")]
        private Int32 mGravtity = 1000;
        [Description("重力加速度")]
        [DisplayName("重力加速度")]
        [Category("重力加速度")]
        [DefaultValue(1000)]
        public Int32 Gravtity { get { return mGravtity; } set { mGravtity = value; } }

        #endregion

        #region hit result on ground

        [FoldoutGroup("Split/受击结果:地面", false)]
        private String mFloorDownHit = "H0070";
        [Description("受到倒地追击攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("倒地追击")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0070")]
        public String FloorDownHit { get { return mFloorDownHit; } set { mFloorDownHit = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorFallDown = "H0031";
        [Description("受到倒地攻击时的动作ID号，此为默认动作号码H0031，每个Action自己可以覆盖此方法")]
        [DisplayName("跌倒")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0031")]
        public String FloorFallDown { get { return mFloorFallDown; } set { mFloorFallDown = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorDiagUp = "H0030";
        [Description("受到浮空攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("浮空")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0030")]
        public String FloorDiagUp { get { return mFloorDiagUp; } set { mFloorDiagUp = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorAirHit = "H0070";
        [Description("受到浮空追击攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("浮空追击")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0070")]
        public String FloorAirHit { get { return mFloorAirHit; } set { mFloorAirHit = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorKnockDown = "H0070";
        [Description("受到击倒攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击倒")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0070")]
        public String FloorKnockDown { get { return mFloorKnockDown; } set { mFloorKnockDown = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorKnockOut = "H0010";
        [Description("受到击飞攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击飞")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0010")]
        public String FloorKnockOut { get { return mFloorKnockOut; } set { mFloorKnockOut = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorKnockBack = "H0070";
        [Description("受到击退攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击退")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0070")]
        public String FloorKnockBack { get { return mFloorKnockBack; } set { mFloorKnockBack = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorStandHit = "H0070";
        [Description("站立受击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("站立受击")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0070")]
        public String FloorStandHit { get { return mFloorStandHit; } set { mFloorStandHit = value; } }

        [FoldoutGroup("Split/受击结果:地面")]
        private String mFloorHold = "H0050";
        [Description("受到抓住攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("抓住")]
        [Category("做:受击结果:地面")]
        [DefaultValue("H0050")]
        public String FloorHold { get { return mFloorHold; } set { mFloorHold = value; } }

        #endregion

        #region hit result in area

        [FoldoutGroup("Split/受击结果:空中", false)]
        private String mAirDownHit = "H0060";
        [Description("受到倒地追击攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("倒地追击")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0060")]
        public String AirDownHit { get { return mAirDownHit; } set { mAirDownHit = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirFallDown = "H0031";
        [Description("受到倒地攻击时的动作ID号，此为默认动作号码H0031，每个Action自己可以覆盖此方法")]
        [DisplayName("跌倒")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0031")]
        public String AirFallDown { get { return mAirFallDown; } set { mAirFallDown = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirDiagUp = "H0030";
        [Description("受到浮空攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("浮空")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0030")]
        public String AirDiagUp { get { return mAirDiagUp; } set { mAirDiagUp = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirAirHit = "H0060";
        [Description("受到浮空追击攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("浮空追击")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0060")]
        public String AirAirHit { get { return mAirAirHit; } set { mAirAirHit = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirKnockDown = "H0040";
        [Description("受到击倒攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击倒")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0040")]
        public String AirKnockDown { get { return mAirKnockDown; } set { mAirKnockDown = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirKnockOut = "H0010";
        [Description("受到击飞攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击飞")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0010")]
        public String AirKnockOut { get { return mAirKnockOut; } set { mAirKnockOut = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirKnockBack = "H0010";
        [Description("受到击退攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击退")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0010")]
        public String AirKnockBack { get { return mAirKnockBack; } set { mAirKnockBack = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirStandHit = "H0060";
        [Description("站立受击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("站立受击")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0060")]
        public String AirStandHit { get { return mAirStandHit; } set { mAirStandHit = value; } }

        [FoldoutGroup("Split/受击结果:空中")]
        private String mAirHold = "H0050";
        [Description("受到抓住攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("抓住")]
        [Category("做:受击结果:空中")]
        [DefaultValue("H0050")]
        public String AirHold { get { return mAirHold; } set { mAirHold = value; } }

        #endregion

        #region hit result in stand

        [FoldoutGroup("Split/受击结果:站立", false)]
        private String mStandDownHit = "H0070";
        [Description("受到倒地追击攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("倒地追击")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0070")]
        public String StandDownHit { get { return mStandDownHit; } set { mStandDownHit = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandFallDown = "H0031";
        [Description("受到倒地攻击时的动作ID号，此为默认动作号码H0031，每个Action自己可以覆盖此方法")]
        [DisplayName("跌倒")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0031")]
        public String StandFallDown { get { return mStandFallDown; } set { mStandFallDown = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandDiagUp = "H0030";
        [Description("受到浮空攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("浮空")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0030")]
        public String StandDiagUp { get { return mStandDiagUp; } set { mStandDiagUp = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandAirHit = "H0060";
        [Description("受到浮空追击攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("浮空追击")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0060")]
        public String StandAirHit { get { return mStandAirHit; } set { mStandAirHit = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandKnockDown = "H0040";
        [Description("受到击倒攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击倒")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0040")]
        public String StandKnockDown { get { return mStandKnockDown; } set { mStandKnockDown = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandKnockOut = "H0010";
        [Description("受到击飞攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击飞")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0010")]
        public String StandKnockOut { get { return mStandKnockOut; } set { mStandKnockOut = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandKnockBack = "H0020";
        [Description("受到击退攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("击退")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0020")]
        public String StandKnockBack { get { return mStandKnockBack; } set { mStandKnockBack = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandStandHit = "H0000";
        [Description("站立受击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("站立受击")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0000")]
        public String StandStandHit { get { return mStandStandHit; } set { mStandStandHit = value; } }

        [FoldoutGroup("Split/受击结果:站立")]
        private String mStandHold = "H0050";
        [Description("受到抓住攻击时的动作ID号，此为默认动作号码，每个Action自己可以覆盖此方法")]
        [DisplayName("抓住")]
        [Category("做:受击结果:站立")]
        [DefaultValue("H0050")]
        public String StandHold { get { return mStandHold; } set { mStandHold = value; } }

#endregion


        public override string ToString()
        {
            String name = "动作组" + GroupNum;

            if (Desc.Length != 0)
                name += "[" + Desc + "]";

            return name;
        }

        public Object Clone()
        {
            // save current object to xml.
            MemoryStream memoryStream = new MemoryStream();
            XmlSerializer serializer = new XmlSerializer(typeof(ActionGroup));
            serializer.Serialize(memoryStream, this);

            // deserializer out.
            memoryStream.Seek(0, SeekOrigin.Begin);
            ActionGroup newActionGroup = (ActionGroup)serializer.Deserialize(memoryStream);
            memoryStream.Close();

            // reset copy datas.
            return newActionGroup;
        }

        public String GetUniqueID(String srcID)
        {
            String KeyChar = srcID.Substring(0, 1);
            int i = int.Parse(srcID.Substring(1));
            while (true)
            {
                String newID = KeyChar + i.ToString("D4");
                bool isUnique = true;
                foreach (Action tmpAction in ActionList)
                {
                    if (newID == tmpAction.ID)
                    {
                        isUnique = false;
                        break;
                    }
                }

                if (isUnique)
                    break;
                i++;
            }
            return KeyChar + i.ToString("D4");
        }

        public Action GetAction(String actionID)
        {
            foreach (Action action in ActionList)
            {
                if (action.ID == actionID)
                    return action;
            }
            return null;
        }

        public string NormalizeActionID(String actionID)
        {
            for (int i = 1; i < actionID.Length; i++)
            {
                if (!char.IsDigit(actionID[i]))
                    return actionID.Substring(0, i);
            }
            return actionID;
        }

        public int GetActionIdx(String actionID)
        {
            actionID = NormalizeActionID(actionID);

            int idx = -1;
            foreach (Action action in ActionList)
            {
                idx++;
                if (action.ID == actionID)
                    return idx;
            }
            return idx;
        }

        public Action GetAction(int idx)
        {
            return idx < mActionList.Count ? mActionList[idx] : null;
        }

        public void SortActionList()
        {
            ActionList.Sort(new Action.ActionCompare());
        }

        public void BuildActionCache()
        {
            //AISetting.BuildActionCache(this);

            foreach (Action action in ActionList)
                action.BuildActionCache(this);
        }
    }
}
